﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using EFCore.IDAL;
using System.Data.Entity;
using System.Linq.Expressions;
using EFCore.Common;
using System.Runtime.Remoting.Messaging;


namespace EFCore.DAL
{
   public abstract class BaseDal<T>:IBaseDal<T>  where T:class 
   {
        #region 变量及构造函数

        /// <summary>
        /// DbContext对象
        /// </summary>
        protected DbContext baseContext;

        /// <summary>
        /// 指定类型的实体对象集合
        /// </summary>
        protected DbSet<T> objectSet;

        /// <summary>
        /// 是否为降序
        /// </summary>
        public bool IsDescending { get; set; }

        /// <summary>
        /// 排序属性
        /// </summary>
        public string SortPropertyName { get; set; }

       public dbEntities db
       {
           get
           {
               string threadCacheKey = typeof(dbEntities).FullName;

               object efInstance = CallContext.GetData(threadCacheKey);
               if (efInstance == null)
               {

                   efInstance = new dbEntities();


                   CallContext.SetData(threadCacheKey, efInstance);
               }

               return efInstance as dbEntities;
           }
           
       }

       /// <summary>
        /// 参数化构造函数
        /// </summary>
        /// <param name="context">DbContext对象</param>
        public BaseDal()
        {
            this.baseContext =db ;
            this.objectSet = this.baseContext.Set<T>();

            //this.IsDescending = true;
            //this.SortPropertyName = "ID";
        }       

        #endregion

        /// <summary>
        /// 插入指定对象到数据库中
        /// </summary>
        /// <param name="t">指定的对象</param>
        /// <returns>执行成功返回<c>true</c>，否则为<c>false</c></returns>
        public virtual bool Insert(T t)
        {
            //ArgumentValidation.CheckForNullReference(t, "传入的对象t为空");

            objectSet.Add(t);
            return baseContext.SaveChanges() > 0;
        }
        /// <summary>
        /// 根据指定对象的ID,从数据库中删除指定对象
        /// </summary>
        /// <param name="id">对象的ID</param>
        /// <returns>执行成功返回<c>true</c>，否则为<c>false</c>。</returns>
        public virtual bool Delete(object id)
        {
            T obj = objectSet.Find(id);
            objectSet.Remove(obj);
            return baseContext.SaveChanges() > 0;
        }

       public virtual bool Delete(T t)
       {
           objectSet.Remove(t);
           return baseContext.SaveChanges()>0;
       }

       /// <summary>
        /// 更新对象属性到数据库中
        /// </summary>
        /// <param name="t">指定的对象</param>
        /// <param name="key">主键的值</param>
        /// <returns>执行成功返回<c>true</c>，否则为<c>false</c></returns>
        public virtual bool Update(T t, object key)
        {
            //ArgumentValidation.CheckForNullReference(t, "传入的对象t为空");

            bool result = false;
            T existing = objectSet.Find(key);
            if (existing != null)
            {
                baseContext.Entry(existing).CurrentValues.SetValues(t);
                result = baseContext.SaveChanges() > 0;
            }
            return result;
        }

       public virtual T FindById(object id)
       {
           T obj = objectSet.Find(id);
           return obj;
       }

       /// <summary>
        /// 根据条件查询数据库,如果存在返回第一个对象
        /// </summary>
        /// <param name="match">条件表达式</param>
        /// <returns>存在则返回指定的第一个对象,否则返回默认值</returns>
        public virtual T FindSingle(Expression<Func<T, bool>> match)
        {
            return objectSet.FirstOrDefault(match);
        }

       public  virtual IQueryable<T> GetQueryable()
       {
           IQueryable<T> query = this.objectSet;
           return query;
       }

       /// <summary>
       /// 根据条件表达式返回可查询的记录源
       /// </summary>
       /// <param name="match">查询条件</param>
       /// <param name="orderByProperty">排序表达式</param>
       /// <param name="order"></param>
       /// <param name="isDescending">如果为true则为降序，否则为升序</param>
       /// <returns></returns>
       public virtual IQueryable<T> GetQueryable<TKey>(Expression<Func<T, bool>> match, Expression<Func<T, TKey>> order, bool isDescending = true)
        {
            IQueryable<T> query = this.objectSet;
            if (match != null)
            {
                query = query.Where(match);
            }
            //var param = Expression.Parameter(typeof(T));
            //var body = Expression.Property(param, sortPropertyName);
            //dynamic keySelector = Expression.Lambda(body, param);
            //return isDescending == true ? Queryable.OrderByDescending(query, keySelector) : Queryable.OrderBy(query,keySelector);
            return isDescending == true ? query.OrderByDescending(order) : query.OrderBy(order);
        }

        //private static LabelExpression getLambdaExpression(string propertyName)
        //{
        //    if (cache.ContainsKey(propertyName)) return cache[propertyName];
        //    var param = Expression.Parameter(typeof(T));
        //    var body = Expression.Property(param, propertyName);
        //    var keySelector = Expression.Lambda(body, param);
        //    cache[propertyName] = keySelector;
        //    return keySelector;
        //}

       /// <summary>
       /// 
       /// </summary>
       /// <param name="match"></param>
       /// <returns></returns>
       public virtual IQueryable<T> Find(Expression<Func<T, bool>> match)
       {
           IQueryable<T> query = this.objectSet;
           if (match != null)
           {
               query = query.Where(match);
           }
           return query;
       }

       public virtual IQueryable<T> Find<TKey>(Expression<Func<T, bool>> match, Expression<Func<T, TKey>> order, bool isDescending = true)
       {
           IQueryable<T> query = this.objectSet;
           if (match != null)
           {
               query = query.Where(match);
           }
           return isDescending == true ? query.OrderByDescending(order) : query.OrderBy(order);
       }

       /// <summary>
        /// 根据条件查询数据库,并返回对象集合(用于分页数据显示)
        /// </summary>
        /// <param name="match">条件表达式</param>
        /// <param name="info">分页实体</param>
        /// <returns>指定对象的集合</returns>
        public virtual ICollection<T> FindWithPager(Expression<Func<T, bool>> match, PagerInfo info)
        {
            int pageindex = (info.CurrenetPageIndex < 1) ? 1 : info.CurrenetPageIndex;
            int pageSize = (info.PageSize <= 0) ? 20 : info.PageSize;

            int excludedRows = (pageindex - 1) * pageSize;

            IQueryable<T> query = Find(match);
            info.RecordCount = query.Count();

            return query.Skip(excludedRows).Take(pageSize).ToList();
        }

       public virtual ICollection<T> FindWithPager<TKey>(Expression<Func<T, bool>> match, PagerInfo info,
           Expression<Func<T, TKey>> orderByProperty, bool isDescending = true)
       {
           int pageindex = (info.CurrenetPageIndex < 1) ? 1 : info.CurrenetPageIndex;
           int pageSize = (info.PageSize <= 0) ? 20 : info.PageSize;

           int excludedRows = (pageindex - 1) * pageSize;

           IQueryable<T> query = Find(match);
           info.RecordCount = query.Count();

           query = isDescending == true ? query.OrderByDescending(orderByProperty) : query.OrderBy(orderByProperty);

           return query.Skip(excludedRows).Take(pageSize).ToList();
       }

       public virtual List<TResult> RunSql<TResult>(string sql, params object[] pamrs)
       {
           return baseContext.Database.SqlQuery<TResult>(sql, pamrs).ToList();
       }
   }
}
